package practise.alogrithm.introductionToAlogrithm.dataStructures;

import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.Queue;

/**
 * you can draw a picture for the process, please note that, when storage queue has elements, and inputQueue has elements also, after the reorganize from input to
 * storage, you have to move the original elements in the storage to the end of it..
 */
public class TwoQueueStack<T> implements Iterable<T> {


    private ArrayDeque<T> inputQueue;
    private ArrayDeque<T> storageQueue;

    public TwoQueueStack(){
        inputQueue = new ArrayDeque<>();
        storageQueue = new ArrayDeque<>();
    }

    public void enqueue(T object){
        inputQueue.add(object);
    }

    public T dequeue(){
       return dequeue(inputQueue,storageQueue);
    }

    private T dequeue(Queue<T> input, Queue<T> output){
        if(input.isEmpty() && output.isEmpty())
            throw new IndexOutOfBoundsException();
        else if(!input.isEmpty())
            resetQueue(input,output);
        return output.poll();
    }

    private void resetQueue(Queue<T> input, Queue<T> output){
        int size = output.size();
        dequeueReccursive(input,output);
        for(int i =0; i < size;i++){
            output.add(output.poll());
        }
    }

    private void dequeueReccursive(Queue<T> input, Queue<T> output){
        if(input.size()==0){
            return ;
        }

        T obj = input.poll();

        dequeueReccursive(input,output);
        output.add(obj);
    }

    @Override
    public Iterator<T> iterator() {
        return new InnerQueueIterator(inputQueue,storageQueue);
    }

    class InnerQueueIterator implements Iterator<T>{
        private ArrayDeque<T> innerinput;
        private ArrayDeque<T> inneroutput;

        InnerQueueIterator(ArrayDeque<T> input, ArrayDeque<T> output) {
            this.innerinput = input.clone();
            this.inneroutput = output.clone();

        }

        @Override
        public boolean hasNext() {
            return !inneroutput.isEmpty()|| !innerinput.isEmpty();
        }

        @Override
        public T next() {

            return dequeue(innerinput,inneroutput);
        }
    }

    public static void main(String[] args){
        TwoQueueStack<Integer> stack = new TwoQueueStack<>();
        for(int i =0 ; i <5 ; i++){
            stack.enqueue(i);
        }
        System.out.println("first:"+stack.dequeue());
        for(int i=6;i<10;i++){
            stack.enqueue(i);
        }
        for(Integer value : stack){
            System.out.print("["+value+"]");
        }
    }
}
